/*! @brief Onedimensional interpolation.
 *
 * @author jiffra@gmail.com
 *
 */

# include <vector>
# include <memory>

# include "config.hpp"

namespace interpolation {

    /*! @brief Function interface
     */
    class function {
    public:
      /*! @brief Computes value at given point.
       *
       * @param x point of interpolation.
       * @return value at x.
       *
       */
       virtual NumType operator()(NumType x) const = 0;

       /*! @brief Destructor.
        */
      virtual ~function() noexcept {}
    };


    /*! @brief Simple linear interpolation
     */
    class LinearInterpolator : public function {
    public:
        /*! @brief Creates interpolator from vectors.
         *
         * @param xs nodes of interpolation.
         * @param ys values of interpolated function.
         */
        LinearInterpolator(std::vector<NumType> const& xs, std::vector<NumType> const& ys);

        /*! @brief Destructor.
         */
        virtual ~LinearInterpolator() noexcept {}

        /*! @brief Computes value at point.
         */
        virtual NumType operator()(NumType x) const;

    private:

        std::shared_ptr<std::vector<NumType>> nodes_;
        std::vector<NumType> values_;
    };


    /*! @brief Polynomial interpolation
     */
    class polynom : public function {
    public:
        /*! @brief Creates polynomial interpoation with given nodes.
         */
        polynom(std::vector<NumType> const& xs, std::vector<NumType> const& ys);

        /*! @brief Destructor.
         */
        virtual ~polynom() noexcept {}

        /*! @brief Computes values at the given point.
         */
        virtual NumType operator()(NumType x) const;

    private:

        std::vector<NumType> nodes_;
        std::vector<NumType> differences_;
    };


    /*! @brief Cubic spline interpolation.
     */
    class cubic_spline : public function {
    public:
        /*! @brief Constructor.
         */
        cubic_spline(std::vector<NumType> const& xs, std::vector<NumType> const& ys);

        /*! @brief Destructor.
         */
        virtual ~cubic_spline() noexcept {}

        /*! @brief Computes value at given point.
         */
        virtual NumType operator() (NumType x) const;

    private:

        std::vector<NumType> nodes_;
        std::vector<NumType> values_;
        std::vector<NumType> ms_;
    };


    /*! @brief Hermit spline interpolation.
     */
    class hermite_spline : public function {
    public:
        /*! @brief Constructor
         */
        hermite_spline(std::vector<NumType> const& xs, std::vector<NumType> const& ys);

        /*! @brief Destructor
         */
        virtual ~hermite_spline() noexcept {}

        /*! @brief Computes value at the given point
         */
        virtual NumType operator() (NumType x) const;

    private:

        std::vector<NumType> nodes_;
        std::vector<NumType> values_;
        std::vector<NumType> derivatives_;
    };

} // namespace interpolation
